package br.ufrrj.im.redes.view;

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;
import javax.swing.JTextField;
import javax.swing.border.LineBorder;
import javax.swing.text.MaskFormatter;

import java.awt.Color;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.JLabel;
import javax.swing.JRadioButton;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JFormattedTextField;

import br.ufrrj.im.redes.client.Client;
import br.ufrrj.im.redes.util.Constants;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.UnknownHostException;
import java.text.ParseException;


public class LoginClientWindow {
	
	private JFrame frmLogin;
	private JTextField textField_User;
	private JPanel panel;
	private JButton btnautenticar;
	private JButton btnSair;
	private JPanel panel_1;
	private JLabel lblIpDoServidor;
	private JLabel lblModo;
	private JRadioButton rdbtnJogador;
	private JRadioButton rdbtnEspectador;
	private JMenuBar menuBar;
	private JMenu mnServidor;
	private JMenuItem mntmCriarServidor;
	private JFormattedTextField TextField_IP;
	private MaskFormatter maskData;
	
	private int mode;
	private String user;
	private String server_IP;
	private Client client;
	
	private void exit(){
		frmLogin.setVisible(false);
		System.exit(1);
	}
	
	
	private void createServer(){
		try {
			Runtime.getRuntime().exec("java -jar server.jar");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private void selectAuthenticationMode(int mode){
		this.mode = mode;
	}
	
	private void authenticate(){

		//valida as entradas e requisita conexão de autenticação com o servidor
		if(validateInputs()){
			
			if(connectToServer()){
				WaitStartGameWindow wait = new WaitStartGameWindow(this.client.getUser());
				wait.showWindow();
				this.frmLogin.setVisible(false);
			}
		}
		else{
			
			JOptionPane.showMessageDialog(frmLogin, "Entradas inválidas, verifique se o nome do usuário foi preenchido \nou se o endereço de IP do servidor também o foi!", "Erro. Entradas inválidas", JOptionPane.ERROR_MESSAGE);
		}
			
	}
	
	private boolean connectToServer(){
		
		int codeAuthentication;
		
		try {
			
			this.client = new Client(this.server_IP, this.user, this.mode);
			
			//requisita a autenticação com o servidor
			codeAuthentication = this.client.requestConnectionToServer();
			
			switch (codeAuthentication) {
			case Constants.AUTHENTICATION_ACCEPT:
					JOptionPane.showMessageDialog(frmLogin, "Conexão estabelecida com o servidor.\nUsuário: " + this.user + " autenticado com sucesso!", "Usuário autenticado com sucesso", JOptionPane.INFORMATION_MESSAGE);
					return true;
			
			case Constants.AUTHENTICATION_USER_INVALID:
				JOptionPane.showMessageDialog(frmLogin, "Conexão não estabelecida com o servidor.\nJá existe um usuário com nome: " + this.user + " autenticado", "Falha na autenticação do usuário", JOptionPane.ERROR_MESSAGE);
				return false;
				
			case Constants.AUTHENTICATION_GAME_STARTED:
				JOptionPane.showMessageDialog(frmLogin, "Conexão não estabelecida com o servidor.\nJogo já inicializado, não é possível estabelecer uma nova conexão", "Falha na autenticação do usuário", JOptionPane.ERROR_MESSAGE);
				return false;
			
			case Constants.AUTHENTICATION_GAME_ERROR:
				JOptionPane.showMessageDialog(frmLogin, "Conexão não estabelecida com o servidor.\nErro desconhecido!", "Falha na autenticação do usuário", JOptionPane.ERROR_MESSAGE);
				return false;
				
			default:
				JOptionPane.showMessageDialog(frmLogin, "Conexão não estabelecida com o servidor.\nErro desconhecido!", "Falha na autenticação do usuário", JOptionPane.ERROR_MESSAGE);
				return false;
			}
			
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			JOptionPane.showMessageDialog(frmLogin, e.toString(), "Falha na autenticação do usuário", JOptionPane.ERROR_MESSAGE);
			return false;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			JOptionPane.showMessageDialog(frmLogin, e.toString(), "Falha na autenticação do usuário", JOptionPane.ERROR_MESSAGE);
			return false;
		}
	}
	
	private boolean validateInputs(){
		
		return ((textField_User.getText().compareTo("") != 0) && (validateIPAdrres()));
	}
	
	private boolean validateIPAdrres(){
		
		String[] ipBlocks = new String[4];
		
		for (int i = 0; i < 16; i+=4) {
			
			ipBlocks[i/4] = TextField_IP.getText().substring(i, i + 3).replaceAll(" ", "");
			
			if(ipBlocks[i/4].compareTo("") == 0)
				return false;
		}
			
		return true;
	}
	
	public void showWindow(){
		this.frmLogin.setVisible(true);
	}

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					LoginClientWindow window = new LoginClientWindow();
					window.frmLogin.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public LoginClientWindow(String user, String server_IP) {
		this.user = user;
		this.server_IP = server_IP;
		initialize();
	}
	
	public LoginClientWindow() {
		this.user = "";
		this.server_IP = "";
		initialize();
	}
	
	public LoginClientWindow(String user) {
		this.user = user;
		this.server_IP = "";
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frmLogin = new JFrame();
		frmLogin.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				exit();
			}
		});
		frmLogin.setTitle("Login");
		frmLogin.setResizable(false);
		frmLogin.setBounds(100, 100, 342, 400);
		frmLogin.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		
		panel = new JPanel();
		panel.setBorder(new TitledBorder(new LineBorder(new Color(184, 207, 229)), "Dados da conex\u00E3o", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		
		
		btnautenticar = new JButton("Autenticar");
		btnautenticar.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				
				user = textField_User.getText();
				server_IP = TextField_IP.getText().replaceAll(" ", "");;
				authenticate();
				
			}
		});
		btnautenticar.setMnemonic('A');
		
		
		btnSair = new JButton("Sair");
		btnSair.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				exit();
			}
		});
		btnSair.setMnemonic('S');

		
		panel_1 = new JPanel();
		panel_1.setBorder(new TitledBorder(null, "Usu\u00E1rio", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		GroupLayout groupLayout = new GroupLayout(frmLogin.getContentPane());
		groupLayout.setHorizontalGroup(
			groupLayout.createParallelGroup(Alignment.LEADING)
				.addGroup(groupLayout.createSequentialGroup()
					.addGap(58)
					.addComponent(btnautenticar)
					.addPreferredGap(ComponentPlacement.RELATED)
					.addComponent(btnSair, GroupLayout.PREFERRED_SIZE, 95, GroupLayout.PREFERRED_SIZE)
					.addContainerGap(73, Short.MAX_VALUE))
				.addGroup(groupLayout.createSequentialGroup()
					.addGap(27)
					.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
						.addComponent(panel, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 280, Short.MAX_VALUE)
						.addComponent(panel_1, Alignment.LEADING, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
					.addGap(33))
		);
		groupLayout.setVerticalGroup(
			groupLayout.createParallelGroup(Alignment.TRAILING)
				.addGroup(groupLayout.createSequentialGroup()
					.addGap(23)
					.addComponent(panel_1, GroupLayout.PREFERRED_SIZE, 61, GroupLayout.PREFERRED_SIZE)
					.addGap(18)
					.addComponent(panel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
					.addGap(18)
					.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
						.addComponent(btnautenticar)
						.addComponent(btnSair))
					.addContainerGap())
		);
		
		textField_User = new JTextField();
		textField_User.setText(user);
		
		textField_User.setColumns(10);
		GroupLayout gl_panel_1 = new GroupLayout(panel_1);
		gl_panel_1.setHorizontalGroup(
			gl_panel_1.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel_1.createSequentialGroup()
					.addContainerGap()
					.addComponent(textField_User, GroupLayout.PREFERRED_SIZE, 235, GroupLayout.PREFERRED_SIZE)
					.addContainerGap(23, Short.MAX_VALUE))
		);
		gl_panel_1.setVerticalGroup(
			gl_panel_1.createParallelGroup(Alignment.LEADING)
				.addGroup(Alignment.TRAILING, gl_panel_1.createSequentialGroup()
					.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
					.addComponent(textField_User, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
					.addContainerGap())
		);
		panel_1.setLayout(gl_panel_1);
		
		
		lblIpDoServidor = new JLabel("IP do servidor:");
		
		
		lblModo = new JLabel("Modo:");
		
		rdbtnJogador = new JRadioButton("Jogador");
		rdbtnJogador.setSelected(true);
		this.mode = Constants.GAMER_MODE;
		rdbtnJogador.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				
				selectAuthenticationMode(Constants.GAMER_MODE);
				rdbtnJogador.setSelected(true);
				rdbtnEspectador.setSelected(false);
				
			}
		});
		
		rdbtnEspectador = new JRadioButton("Espectador");
		rdbtnEspectador.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				
				selectAuthenticationMode(Constants.SPECTATOR_MODE);
				
				rdbtnEspectador.setSelected(true);
				rdbtnJogador.setSelected(false);
				
			}
		});
		
		TextField_IP = new JFormattedTextField();
		try {
			maskData = new MaskFormatter("###.###.###.###");
			maskData.install(TextField_IP);
		} catch (ParseException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		TextField_IP.setText(server_IP);
		
		
		GroupLayout gl_panel = new GroupLayout(panel);
		gl_panel.setHorizontalGroup(
			gl_panel.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel.createSequentialGroup()
					.addContainerGap()
					.addGroup(gl_panel.createParallelGroup(Alignment.LEADING)
						.addGroup(gl_panel.createSequentialGroup()
							.addComponent(TextField_IP, GroupLayout.PREFERRED_SIZE, 235, GroupLayout.PREFERRED_SIZE)
							.addContainerGap())
						.addGroup(gl_panel.createSequentialGroup()
							.addGroup(gl_panel.createParallelGroup(Alignment.LEADING)
								.addComponent(lblIpDoServidor)
								.addComponent(lblModo)
								.addGroup(gl_panel.createSequentialGroup()
									.addComponent(rdbtnJogador)
									.addPreferredGap(ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
									.addComponent(rdbtnEspectador)))
							.addContainerGap(23, Short.MAX_VALUE))))
		);
		gl_panel.setVerticalGroup(
			gl_panel.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel.createSequentialGroup()
					.addGap(22)
					.addComponent(lblIpDoServidor)
					.addPreferredGap(ComponentPlacement.RELATED)
					.addComponent(TextField_IP, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
					.addGap(26)
					.addComponent(lblModo)
					.addPreferredGap(ComponentPlacement.UNRELATED)
					.addGroup(gl_panel.createParallelGroup(Alignment.BASELINE)
						.addComponent(rdbtnJogador)
						.addComponent(rdbtnEspectador))
					.addContainerGap(13, Short.MAX_VALUE))
		);
		panel.setLayout(gl_panel);
		frmLogin.getContentPane().setLayout(groupLayout);
		
		menuBar = new JMenuBar();
		frmLogin.setJMenuBar(menuBar);
		
		
		mnServidor = new JMenu("Servidor");
		mnServidor.setMnemonic('S');
		menuBar.add(mnServidor);
		
		mntmCriarServidor = new JMenuItem("Criar servidor");
		mntmCriarServidor.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				createServer();
			}
		});
		mnServidor.add(mntmCriarServidor);
	}
}
